#include <iostream>
#include <list>
#include <errno.h>
#include "BaseDeDatos.h"
#include <Cola.h>
#include <mensajes.h>
#include "tools/SignalHandler.h"
#include "INTERRUPT_Handler.h"

using namespace std;

int main(int argc, char* argv[]) {
	cout << "GESTOR BASE DE DATOS" << endl;
	cout << "------ ---- -- -----" << endl << endl;

	BaseDeDatos* BD = new BaseDeDatos();

	int error = BD->abrir();

	switch (error) {
	case 0:
	{
		Cola<mensajes::ConsultaType> colaConsultas(ARCHIVO_COLAS,LETRA_CONSULTAS);
		Cola<mensajes::RespuestaType> colaRespuestas(ARCHIVO_COLAS,LETRA_RESPUESTAS);

		// event handler para la senial SIGINT (-2)
		INTERRUPT_Handler interrupt_handler;
		SignalHandler::getInstance()->registrarHandler ( SIGINT,&interrupt_handler );

		cout << "La base se creo correctamente." << endl;

		bool salir = false;

		while (!salir) {
			mensajes::ConsultaType consulta;

			cout << "Esperando consultas..." << endl;
			int error = colaConsultas.leer(0,&consulta);

			if (error < 0) {
				if (errno != EINTR) {
					if (errno == EIDRM) {
						cout << "La cola de mensajes fue removida." << endl << endl;
						salir = true;
					} else {
						cout << "Error en consulta recibida." << endl << endl;
					}
				} else {
					cout << "Gestor interrumpido." << endl;
					salir = true;
				}
			} else {
				cout << "Consulta recibida: " << endl;
				list<mensajes::RespuestaType> respuestas = BD->ejecutar(consulta);

				cout << "\t" << "Enviando respuesta..." << endl;

				list<mensajes::RespuestaType>::const_iterator end = respuestas.end();
				list<mensajes::RespuestaType>::const_iterator it = respuestas.begin();
				for (; it != end; ++it) {
					colaRespuestas.escribir(*it);
				}

				cout << "\t" << "Respuesta enviada." << endl << endl;
			}
		}
		SignalHandler::getInstance()->removerHandler(SIGINT);
		SignalHandler::getInstance()->destruir();
		colaConsultas.destruir();
		colaRespuestas.destruir();
		cout << "Servidor cerrado." << endl;
		break;
	}
	case -1:
		cout << "ERROR: Ya hay un gestor corriendo." << endl;
		break;
	case -2:
		cout << "ERROR: No se pudo crear la base de datos." << endl;
		break;
	}

	BD->cerrar();

	delete BD;

	return error;
}
